package controllers;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.Toolkit;
import java.io.*;

/**
 * This class implements an internal system clock for the system.
 * The clock has a multiplier, MS_MULTIPLIER, that can be set to accelerate the system clock for simulation purposes.
 * If the MS_MULTIPLIER equals to 1, the 'real' time is returned.
 * @author Alon Shahaf
 * @Data 12.01.2013
 */

public class IntSysClock 
{
	private Date		boot_date;
	private Date		isys_date;
	public DateFormat 	dateFormat;
	
    Toolkit toolkit;
    Timer timer;
    
    /**
     * Starts a new internal system clock.
     */ 
	@SuppressWarnings("unused")
	public IntSysClock()
	{
		Calendar 	intCal;
		System.out.println("System Clock Started!");
		this.dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
		
		// Set boot date and system date to be the current REAL time
		intCal = Calendar.getInstance();
		this.boot_date = intCal.getTime();
		this.isys_date = intCal.getTime();
		
		// Restore Internal System Clock if needed.
		if (OBLSettings.MS_MULTIPLIER != 1)
		{
			Date txt_date=this.boot_date;
		    try 
		    {
		    	FileInputStream fstream = new FileInputStream(OBLSettings.txtClockFilePath);
		    	// Get the object of DataInputStream
		    	DataInputStream in = new DataInputStream(fstream);
		    	BufferedReader br = new BufferedReader(new InputStreamReader(in));

		    	String txt_date_string = null;
		    	txt_date_string = br.readLine();
		    	//Close the input stream
		    	in.close();
		    	txt_date = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").parse(txt_date_string);
			}
		    catch (IOException e) 
		    {
				System.out.println("IntSysClock (Cons.) Unable to open INI file!");
				System.exit(0);
			}
		    catch (ParseException e)
		    {
				System.out.println("IntSysClock (Cons.) Bad date format in INI file!");
				System.exit(0);	    	
		    }
		    catch (NullPointerException e)
		    {
				System.out.println("IntSysClock (Cons.) NullPointer Exception!");
				System.exit(0);		    	
		    }
		    if (txt_date.after(boot_date)) 
		    	setIsys_date(txt_date);
		    System.out.println("IntSysClock (Cons.)  INT. SYS DATE SET TO:" + getIsys_date().toString());
		}

		//startTimer();
	}
	
    /**
     * Returns the current internal system time and date.
     * @return current time and date.
     */	
	@SuppressWarnings("unused")
	public Date getTime()
	{
		Calendar current_cal = Calendar.getInstance();
		Calendar tempBootCal = Calendar.getInstance();
		
		if (OBLSettings.MS_MULTIPLIER == 1)			// Return current REAL time.
			return current_cal.getTime();
		
		Date newTime;
		newTime = current_cal.getTime();				// TODO - remove this later
		String now_string = dateFormat.format(newTime);	// TODO - remove this later

		tempBootCal.setTime(getBoot_date());
		long runtime_ms = current_cal.getTimeInMillis() - tempBootCal.getTimeInMillis();
		long runtime_sec = runtime_ms / 1000;
		//long runtime_min = runtime_ms / (60 * 1000);
		//long runtime_hours = runtime_ms / (60 * 60 * 1000);
		//long runtime_days = runtime_ms / (24 * 60 * 60 * 1000);
		
		tempBootCal.setTime(getIsys_date());
		//tempBootCal.add(Calendar.SECOND, ((int) runtime_sec) * OBLSettings.SEC_MULTIPLIER);
		tempBootCal.setTimeInMillis(tempBootCal.getTimeInMillis() + runtime_ms * OBLSettings.MS_MULTIPLIER);	// Using MS allows us to increase time in LONG variables instead of INT using seconds.
		
		newTime = tempBootCal.getTime();
		String int_string = dateFormat.format(newTime);	// TODO - remove this later
		//System.out.println("IntSysClock (getTime) RunTime(sec)="+runtime_sec+ " | REAL_DATE="+now_string+"  ==> INT_CLK="+int_string); // TODO - remove this later

		return newTime;
	}
	
    /**
     * Save the current internal system time and date for next boot.
     */
	public void saveIsysTime()
	{
		Date save_date;
		String save_date_string="-";
	    try 
	    {
	    	save_date = getTime();
	    	save_date_string = dateFormat.format(save_date);
	    	FileWriter fw = new FileWriter(OBLSettings.txtClockFilePath,false);
	    	fw.write(save_date_string);
	    	fw.close();
		}
	    catch (IOException e) 
	    {
			System.out.println("IntSysClock (saveIsysTime) Unable to open INI file!");
			System.exit(0);
		}
	    System.out.println("IntSysClock (saveIsysTime) Saved time ("+save_date_string+") for next boot in TXT file.");
	}
	
    /**
     * Returns the boot time and date.
     * @return the boot time and date.
     */
	public Date getBoot_date() 
	{
		//System.out.println("IntSysClock (getBoot_date) boot_date="+boot_date.toString());
		return boot_date;
	}

    /**
     * Returns the internal system time and date.
     * @return the internal system time and date.
     */
	public Date getIsys_date() 
	{
		return isys_date;
	}

	/**
     * Sets the internal system time and date
     * @param the internal system time and date.
     */
	public void setIsys_date(Date isys_date) 
	{
		this.isys_date = isys_date;
	}

	/**
     * Starts a new timer to run a scheduled task.
     * @deprecated
     */
    public void startTimer() 
    {
    	toolkit = Toolkit.getDefaultToolkit();
        timer = new Timer();
        timer.schedule(new RemindTask(),
	               0,        //initial delay
	               1*1000);  //subsequent rate
    }
    
	/**
     * Remind task timer class holds the function to run when the timer time is due.
     * @deprecated
     */    
    class RemindTask extends TimerTask 
    {
    	int loopCounter = 5;

    	    public void run() 
    	    {
    	    	if (loopCounter > 0) 
    	    	{
    	    		//System.out.format("TIME = "+getTime()+"\n");
    	    		getTime();
    	    		loopCounter--;
    	    	}
    	    	else
    	    	{
    	            System.out.format("RemindTask finished!%n");
    	            timer.cancel(); //Not necessary because we call System.exit
    	            //System.exit(0);   //Stops the AWT thread (and everything else)
    	    	}
    	    }
    }
    
}


